#include <sys/types.h>   
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>   
#include <stdio.h>       
#include <stdlib.h>      
#include <string.h>      
#include <unistd.h>      

#define MAX_LEN  1024    /* maximum string size to send */
#define MIN_PORT 1024    /* minimum port allowed */
#define MAX_PORT 65535   /* maximum port allowed */

int REQUEST_INTERVAL = 5;	/* in seconds */

#define SOCKET_ERROR -1

int isReadable(int sd, int timeOut) 
{   
  fd_set socketReadSet;
  FD_ZERO(&socketReadSet);
  FD_SET(sd,&socketReadSet);

  struct timeval tv;
  if (timeOut) 
  {
    tv.tv_sec  = timeOut / 1000;
    tv.tv_usec = (timeOut % 1000) * 1000;
  } 
  else 
  {
    tv.tv_sec  = 0;
    tv.tv_usec = 0;
  } 
  
  if (select(sd+1,&socketReadSet,0,0,&tv) == SOCKET_ERROR) 
  {
    return 0;
  } 
  
  return FD_ISSET(sd,&socketReadSet) != 0;
} 


int main(int argc, char *argv[]) 
{
	int sock;					/* socket to send packt to FM*/
	struct sockaddr_in  server_addr, client_addr, echo_server_addr;	
	char*	fm_addr_str;			/* fault manager's IP address (for eg, killerbee1.cc.gatech.edu [130.207.127.231]) */
	unsigned short fm_port;		    /* fault manager's port that listen to load balancer/GUI */
	unsigned int type;

	/* validate number of arguments */
	if (argc != 5) 
	{
		fprintf(stderr, "Usage: %s <FM IP> <FM Port> <Requestor Node Type> <REQUEST INTERVAL> [Type: Load Balancer = 3, GUI = 4]\n", argv[0]);
		exit(1);
	}


	fm_addr_str = argv[1];			
	fm_port = atoi (argv[2]);	
	type = atoi (argv[3]);	
	REQUEST_INTERVAL = atoi (argv[4]);


	/* validate the port range */
	if ( (fm_port < MIN_PORT || fm_port > MAX_PORT)  ) 
	{
		fprintf(stderr, "Invalid port number argument\n");
		fprintf(stderr, "Valid range is between %d and %d.\n", MIN_PORT, MAX_PORT);
		exit(1);
	}


	if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 
	{
		perror("sock failed");
		exit(1);
	}	    


	memset (&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family      = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr(fm_addr_str);
	server_addr.sin_port        = htons(fm_port);


  /* bind any port to listen*/
	memset (&client_addr, 0, sizeof(client_addr));
	client_addr.sin_family      = AF_INET;
	client_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	client_addr.sin_port        = htons(0);

  	if ((bind(sock, (struct sockaddr *) &client_addr, sizeof(client_addr))) < 0) 
	{
    	perror("bind() failed");
    	exit(1);
  	}


	int request_count = 0;
	int timeout = 100;	//ms

	for ( ; ;)			/* repeatedly asks FM for sending active node list */
	{
		char send_str[MAX_LEN];     /* string to send */
		unsigned int send_len;      /* length of string to send */
		char recv_str[MAX_LEN];     /* string to send */
		unsigned int recv_len;      /* length of string to send */
  		struct sockaddr_in echo_server_addr; /* packet source */
  		unsigned int echo_len;        /* source addr length */


		/* clear send buffer */
		memset(send_str, 0, sizeof(send_str));
		sprintf (send_str, "%d, %d\n", type, ++request_count);
		send_len = strlen(send_str);


		if ((sendto(sock, send_str, send_len, 0, (struct sockaddr *) &server_addr, sizeof(server_addr))) != send_len ) 
		{
			perror("sendto() sent incorrect number of bytes");
			exit(1);
		}


		/* clear the receive buffers & structs */
		memset(recv_str, 0, sizeof(recv_str));
		echo_len = sizeof(echo_server_addr);
		memset(&echo_server_addr, 0, echo_len);


		/* block waiting to receive a packet */
		if ((recv_len = recvfrom(sock, recv_str, MAX_LEN, 0, (struct sockaddr*) &echo_server_addr, &echo_len)) < 0) 
		{
		  perror("recvfrom() failed");
		  exit(1);
		}

		printf("Received %d bytes from %s [port # %u]: %s", recv_len, inet_ntoa(echo_server_addr.sin_addr), ntohs( echo_server_addr.sin_port), recv_str );

		sleep (REQUEST_INTERVAL);	
	}

	//close(sock);  
	exit(0);
}


